package unify.gui;

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

import javax.swing.JScrollPane;
import javax.swing.JTable;


import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Point;

import javax.swing.SwingConstants;
import java.awt.FlowLayout;
import javax.swing.JButton;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.Insets;
import javax.swing.JList;
import java.awt.CardLayout;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Logger;

import javax.swing.AbstractListModel;
import javax.swing.border.BevelBorder;
import javax.swing.JCheckBox;
import java.awt.Component;
import javax.swing.JTextField;

import unify.ShowLibrary;
import unify.data.Feed;
import unify.data.Search;
import unify.data.Settings;
import unify.data.Show;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;


@SuppressWarnings("serial")
public class GUI extends JFrame {

	private JTabbedPane contentPane;
	private JTable showTable;
	private DefaultTableModel showTableModel;
	private JPanel editShowsTab;
	private JPanel settingsTab;
	private JPanel settingsPanel;
	private JList settingsList;
	private ArrayList<String> settingsItems = new ArrayList<String>();
	private DefaultTableModel feedTableModel;
	private JTable feedTable;
	private DefaultTableModel searchTableModel;
	private JTable searchTable;
	public static JFrame frame;
	private JTextField todayLabel;
	private JTextField todayURL;
	private JTextField tomorrowLabel;
	private JTextField tomorrowURL;
	private JCheckBox chckbxFindNewShows;
	private JCheckBox chckbxTrackMiniseries;
	private JTextField delayTextField;
	private final static Logger LOGGER = Logger.getLogger(SysTrayIcon.class.getName());

	/**
	 * Launch the application.
	 */
	public static void main() {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				if(GUI.frame == null) {
					GUI.getInstance();
				}
				else {
					((JTabbedPane) frame.getContentPane()).setSelectedIndex(0);
				}
				frame.setVisible(true);
				frame.toFront();
				frame.setExtendedState(NORMAL);
				frame.setLocationRelativeTo(null);
			}
		});
	}

	/**
	 * Create the frame.
	 */
	private GUI() {
		setTitle("Unify");
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(0, 0, 800, 600);
		contentPane = new JTabbedPane();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 0));
		setContentPane(contentPane);
		setIconImage(Settings.getInstance().getIconImage());

		createEditShowsTab();
		createSettingsTab();
	}
	
	public static synchronized GUI getInstance() {
		if (frame == null) {
			frame = new GUI();
		}
		return (GUI) frame;
	}
	
	public  void refresh() {
		if(frame!=null) {
			updateShowTable(false);
		}
	}

	private void createEditShowsTab() {
		editShowsTab = new JPanel();
		editShowsTab.setBorder(new EmptyBorder(0, 0, 0, 0));
		GridBagLayout gbl_editShowsTab = new GridBagLayout();
		gbl_editShowsTab.columnWeights = new double[]{0.0};
		gbl_editShowsTab.rowWeights = new double[]{0.0, Double.MIN_VALUE};
		editShowsTab.setLayout(gbl_editShowsTab);
		contentPane.add(editShowsTab, gbl_editShowsTab);
		contentPane.setTitleAt(0, "Edit Shows");
		contentPane.setEnabledAt(0, true);

		createShowTable();
		createBottomPanel();
	}


	private void createBottomPanel() {
		JPanel bottomPanel = new JPanel();
		GridBagConstraints gbc_bottomPanel = new GridBagConstraints();
		gbc_bottomPanel.anchor = GridBagConstraints.SOUTH;
		gbc_bottomPanel.fill = GridBagConstraints.BOTH;
		gbc_bottomPanel.gridx = 0;
		gbc_bottomPanel.gridy = 1;
		editShowsTab.add(bottomPanel, gbc_bottomPanel);
		bottomPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 1));

		JLabel instructions = new JLabel("Double-click to modify, mouse over to view alternate titles.");
		instructions.setHorizontalAlignment(SwingConstants.RIGHT);
		bottomPanel.add(instructions);

		JButton btnAddShow = new JButton("Add Show");
		btnAddShow.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent arg0) {
				String inputShowTitle = JOptionPane.showInputDialog(frame, "Enter the title of the show: ");
				if(inputShowTitle!=null && !inputShowTitle.isEmpty()) {
					String inputSeason = JOptionPane.showInputDialog(frame, "Enter the season number that you are currently watching: ");
					if(inputSeason!=null && !inputSeason.isEmpty()) {
						String inputEpisode = JOptionPane.showInputDialog(frame, "Enter the number of the last episode you've watched: ");
						if(inputEpisode!=null && !inputEpisode.isEmpty()) {
							try {
								ShowLibrary.getInstance().addShow(inputShowTitle, Integer.parseInt(inputSeason), Integer.parseInt(inputEpisode));
								LOGGER.info("Added " + inputShowTitle + " to shows, looking for season " + inputSeason + " episode " + (inputEpisode+1));
								updateShowTable(true);
							} catch (NumberFormatException e) {
								JOptionPane.showMessageDialog(frame, "The value you entered for the season or episode was not an integer, please try again.", "Warning: Not an integer", JOptionPane.ERROR_MESSAGE);
							}
						}
					}
				}
			}
		});
		bottomPanel.add(btnAddShow);

		JButton btnDeleteShow = new JButton("Delete Show");
		btnDeleteShow.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = showTable.getSelectedRow();
				if(row==-1) {
					JOptionPane.showMessageDialog(frame, "Please select a show in the above table first.", "Error", JOptionPane.ERROR_MESSAGE);
				}
				else {
					ShowLibrary showLib = ShowLibrary.getInstance();
					Show show = showLib.shows.get(row);
					int result = JOptionPane.showConfirmDialog(frame,"Are you sure you want to delete " + show.getTitle(), "Delete " + show.getTitle() + "?", JOptionPane.YES_NO_OPTION);
					if(result==0) {
						LOGGER.info("Deleted " + show.getTitle() + ".");
						showLib.shows.remove(show);
						updateShowTable(true);
					}
				}
			}
		});
		bottomPanel.add(btnDeleteShow);

		JButton btnAddAltTitle = new JButton("Add Alternate Title");
		btnAddAltTitle.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = showTable.getSelectedRow();
				if(row==-1) {
					JOptionPane.showMessageDialog(frame, "Please select a show in the above table first.", "Error", JOptionPane.ERROR_MESSAGE);
				}
				else {
					ShowLibrary showLib = ShowLibrary.getInstance();
					Show show = showLib.shows.get(row);
					String altTitle = JOptionPane.showInputDialog(frame,"Enter the alternate title you want to add to " + show.getTitle());
					if(!(altTitle==null || altTitle.isEmpty() || altTitle.startsWith("No alternate")) ) {
						show.addAltTitle(altTitle);
						updateShowTable(true);
					}
				}
			}
		});
		bottomPanel.add(btnAddAltTitle);

		JButton btnRemoveAltTitle = new JButton("Remove Alternate Title");
		btnRemoveAltTitle.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = showTable.getSelectedRow();
				if(row==-1) {
					JOptionPane.showMessageDialog(frame, "Please select a show in the above table first.", "Error", JOptionPane.ERROR_MESSAGE);
				}
				else {
					ShowLibrary showLib = ShowLibrary.getInstance();
					Show show = showLib.shows.get(row);
					String[] altTitles = show.getAltTitles().split("<br>");
					String altTitle = (String) JOptionPane.showInputDialog(frame,"Selecte the alternate title you want to remove from " + show.getTitle(), "Remove alternate title from " + show.getTitle(), JOptionPane.INFORMATION_MESSAGE, null, altTitles, altTitles[0]);
					if(!(altTitle==null || altTitle.isEmpty())) {
						show.removeAltTitle(altTitle);
						updateShowTable(true);
					}
				}
			}
		});
		bottomPanel.add(btnRemoveAltTitle);
	}

	public void createShowTable() {
		showTableModel = new DefaultTableModel(
				new Object[][] {},
				new String[] {"Show Title", "Current Season", "Last Watched Episode"});
		JScrollPane scrollPane = new JScrollPane();
		GridBagConstraints gbc_scrollPane = new GridBagConstraints();
		gbc_scrollPane.weighty = 0.1;
		gbc_scrollPane.weightx = 0.1;
		gbc_scrollPane.fill = GridBagConstraints.BOTH;
		gbc_scrollPane.anchor = GridBagConstraints.NORTH;
		gbc_scrollPane.gridx = 0;
		gbc_scrollPane.gridy = 0;
		editShowsTab.add(scrollPane, gbc_scrollPane);

		showTable = new JTable();
		scrollPane.setViewportView(showTable);
		showTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		showTable.setModel(showTableModel);
		showTableModel.addTableModelListener(new TableModelListener() {
			@Override
			public void tableChanged(TableModelEvent e) {
				int row = e.getFirstRow();
				int col = e.getColumn();

				switch (e.getType()) {
				case TableModelEvent.INSERT:
					//Unused
					break;
				case TableModelEvent.UPDATE:
					Show show = ShowLibrary.getInstance().shows.get(row);
					String value = (String) showTableModel.getValueAt(row, col);
					if(col==0 && !value.isEmpty()) {
						show.setTitle(value);
					}
					else if(col==1) {
						try {
							show.setCurSeason(Integer.parseInt(value));
						}
						catch (NumberFormatException exception) {
							JOptionPane.showMessageDialog(frame, value + " is not an integer, please try again.", "Warning: Not an integer", JOptionPane.ERROR_MESSAGE);
						}
					}
					else if(col==2) {
						try {
							show.setLastEpisode(Integer.parseInt(value));
						}
						catch (NumberFormatException exception) {
							JOptionPane.showMessageDialog(frame, value + " is not an integer, please try again.", "Warning: Not an integer", JOptionPane.ERROR_MESSAGE);
						}
					}
					updateShowTable(true);
					break;
				case TableModelEvent.DELETE:
					//Unused
					break;
				}
			}
		});

		showTable.getColumnModel().getColumn(0).setPreferredWidth(300);

		showTable.addMouseMotionListener(new MouseMotionAdapter(){
			public void mouseMoved(MouseEvent e){
				Point p = e.getPoint(); 
				int row = showTable.rowAtPoint(p);
				showTable.setToolTipText("<html>Alternate titles:<br>" + ShowLibrary.getInstance().shows.get(row).getAltTitles() + "</html>");
			}
		});

		updateShowTable(false);
	}

	private void createSettingsTab() {
		settingsTab = new JPanel();
		settingsTab.setBorder(new EmptyBorder(5, 5, 5, 5));
		GridBagLayout gbl_settingsTab = new GridBagLayout();
		gbl_settingsTab.columnWidths = new int[]{100, 602};
		gbl_settingsTab.columnWeights = new double[]{0.0, 0.0};
		gbl_settingsTab.rowWeights = new double[]{0.0};
		settingsTab.setLayout(gbl_settingsTab);
		contentPane.add(settingsTab, gbl_settingsTab);
		contentPane.setTitleAt(1, "Settings");
		contentPane.setEnabledAt(1, true);

		createSettingsPanel();
		createSettingsList();
		createMainSettingsPanel();
		createFeedSettingsPanel();
		createsearchettingsPanel();
	}

	private void createSettingsPanel() {
		settingsPanel = new JPanel();
		GridBagConstraints gbc_settingsPanel = new GridBagConstraints();
		gbc_settingsPanel.weightx = 0.1;
		gbc_settingsPanel.anchor = GridBagConstraints.EAST;
		gbc_settingsPanel.fill = GridBagConstraints.BOTH;
		gbc_settingsPanel.gridx = 1;
		gbc_settingsPanel.gridy = 0;
		settingsTab.add(settingsPanel, gbc_settingsPanel);
		settingsPanel.setLayout(new CardLayout(0, 0));		
	}

	private void createSettingsList() {
		settingsItems.add("Main Settings");
		settingsItems.add("RSS Feeds");
		settingsItems.add("Search URLs");
		settingsList = new JList();
		settingsList.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
		settingsList.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent arg0) {
				CardLayout cl = (CardLayout)(settingsPanel.getLayout());
				int selection = settingsList.getSelectedIndex();
				if(selection!=-1) {
					cl.show(settingsPanel, settingsItems.get(selection));
				}
			}
		});
		settingsList.setModel(new AbstractListModel() {
			String [] values = settingsItems.toArray(new String[settingsItems.size()]);
			public int getSize() {
				return values.length;
			}
			public Object getElementAt(int index) {
				return values[index];
			}
		});
		GridBagConstraints gbc_settingsList = new GridBagConstraints();
		gbc_settingsList.weighty = 0.1;
		gbc_settingsList.anchor = GridBagConstraints.WEST;
		gbc_settingsList.insets = new Insets(0, 0, 0, 5);
		gbc_settingsList.fill = GridBagConstraints.BOTH;
		gbc_settingsList.gridx = 0;
		gbc_settingsList.gridy = 0;
		settingsTab.add(settingsList, gbc_settingsList);		
	}

	public void createMainSettingsPanel() {
		JPanel mainSettingsPanel = new JPanel();
		settingsPanel.add(mainSettingsPanel, settingsItems.get(0));
		GridBagLayout gbl_mainSettingsPanel = new GridBagLayout();
		gbl_mainSettingsPanel.columnWidths = new int[]{702};
		gbl_mainSettingsPanel.rowHeights = new int[]{30, 30, 30, 30, 30, 0, 30};
		gbl_mainSettingsPanel.columnWeights = new double[]{0.0};
		gbl_mainSettingsPanel.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
		mainSettingsPanel.setLayout(gbl_mainSettingsPanel);

		JPanel todayPanel = new JPanel();
		todayPanel.setAlignmentY(Component.TOP_ALIGNMENT);
		todayPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
		FlowLayout fl_todayPanel = (FlowLayout) todayPanel.getLayout();
		fl_todayPanel.setAlignment(FlowLayout.LEFT);
		GridBagConstraints gbc_todayPanel = new GridBagConstraints();
		gbc_todayPanel.anchor = GridBagConstraints.NORTH;
		gbc_todayPanel.fill = GridBagConstraints.HORIZONTAL;
		gbc_todayPanel.insets = new Insets(0, 0, 5, 0);
		gbc_todayPanel.gridx = 0;
		gbc_todayPanel.gridy = 2;
		mainSettingsPanel.add(todayPanel, gbc_todayPanel);

		JLabel lblWhatsOnToday = new JLabel("What's on today? Feed label:");
		todayPanel.add(lblWhatsOnToday);
		lblWhatsOnToday.setAlignmentY(Component.TOP_ALIGNMENT);

		todayLabel = new JTextField();
		todayPanel.add(todayLabel);
		todayLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
		todayLabel.setAlignmentY(Component.TOP_ALIGNMENT);
		todayLabel.setColumns(10);

		JLabel lblTodayFeedUrl = new JLabel("Feed URL:");
		todayPanel.add(lblTodayFeedUrl);

		todayURL = new JTextField();
		todayPanel.add(todayURL);
		todayURL.setColumns(40);

		chckbxFindNewShows = new JCheckBox("Find new shows");
		chckbxFindNewShows.setToolTipText("Enable this to be notified when a new show (season 1 episode 1) is released on any feed.");
		chckbxFindNewShows.setAlignmentY(Component.TOP_ALIGNMENT);
		GridBagConstraints gbc_chckbxFindNewShows = new GridBagConstraints();
		gbc_chckbxFindNewShows.fill = GridBagConstraints.HORIZONTAL;
		gbc_chckbxFindNewShows.anchor = GridBagConstraints.NORTHWEST;
		gbc_chckbxFindNewShows.insets = new Insets(0, 0, 5, 0);
		gbc_chckbxFindNewShows.gridx = 0;
		gbc_chckbxFindNewShows.gridy = 0;
		mainSettingsPanel.add(chckbxFindNewShows, gbc_chckbxFindNewShows);

		chckbxTrackMiniseries = new JCheckBox("Track miniseries");
		chckbxTrackMiniseries.setToolTipText("Enable this to allow tracking of miniseries");
		chckbxTrackMiniseries.setAlignmentY(Component.TOP_ALIGNMENT);
		GridBagConstraints gbc_chckbxTrackMiniseries = new GridBagConstraints();
		gbc_chckbxTrackMiniseries.fill = GridBagConstraints.HORIZONTAL;
		gbc_chckbxTrackMiniseries.anchor = GridBagConstraints.NORTHWEST;
		gbc_chckbxTrackMiniseries.insets = new Insets(0, 0, 5, 0);
		gbc_chckbxTrackMiniseries.gridx = 0;
		gbc_chckbxTrackMiniseries.gridy = 1;
		mainSettingsPanel.add(chckbxTrackMiniseries, gbc_chckbxTrackMiniseries);

		JPanel tomorrowPanel = new JPanel();
		tomorrowPanel.setAlignmentY(Component.TOP_ALIGNMENT);
		tomorrowPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
		FlowLayout flowLayout = (FlowLayout) tomorrowPanel.getLayout();
		flowLayout.setAlignment(FlowLayout.LEFT);
		GridBagConstraints gbc_tomorrowPanel = new GridBagConstraints();
		gbc_tomorrowPanel.fill = GridBagConstraints.BOTH;
		gbc_tomorrowPanel.insets = new Insets(0, 0, 5, 0);
		gbc_tomorrowPanel.gridx = 0;
		gbc_tomorrowPanel.gridy = 3;
		mainSettingsPanel.add(tomorrowPanel, gbc_tomorrowPanel);

		JLabel lblWhatsOnTomorrow = new JLabel("What's on tomorrow? Feed label:");
		tomorrowPanel.add(lblWhatsOnTomorrow);

		tomorrowLabel = new JTextField();
		tomorrowPanel.add(tomorrowLabel);
		tomorrowLabel.setColumns(10);

		JLabel lblTomorrowFeedUrl = new JLabel("Feed URL:");
		tomorrowPanel.add(lblTomorrowFeedUrl);

		tomorrowURL = new JTextField();
		tomorrowPanel.add(tomorrowURL);
		tomorrowURL.setColumns(40);

		JPanel delayPanel = new JPanel();
		FlowLayout flowLayout_1 = (FlowLayout) delayPanel.getLayout();
		flowLayout_1.setAlignment(FlowLayout.LEFT);
		delayPanel.setAlignmentY(Component.TOP_ALIGNMENT);
		delayPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
		GridBagConstraints gbc_delayPanel = new GridBagConstraints();
		gbc_delayPanel.insets = new Insets(0, 0, 5, 0);
		gbc_delayPanel.anchor = GridBagConstraints.NORTH;
		gbc_delayPanel.fill = GridBagConstraints.HORIZONTAL;
		gbc_delayPanel.gridx = 0;
		gbc_delayPanel.gridy = 4;
		mainSettingsPanel.add(delayPanel, gbc_delayPanel);

		JLabel lblDelayBetweenRss = new JLabel("Delay between RSS feed checks (in minutes):");
		delayPanel.add(lblDelayBetweenRss);

		delayTextField = new JTextField();
		delayPanel.add(delayTextField);
		delayTextField.setColumns(5);

		JButton btnSaveChanges = new JButton("Save Changes");
		btnSaveChanges.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				Settings.getInstance().setFindNewShows(chckbxFindNewShows.isSelected());
				Settings.getInstance().setFindMiniSeries(chckbxTrackMiniseries.isSelected());
				String value = "";
				try {
					value = delayTextField.getText();
					Settings.getInstance().setDelay(Integer.parseInt(value));
				} catch (NumberFormatException e) {
					JOptionPane.showMessageDialog(frame, value + " is not an integer, please try again.", "Warning: Not an integer", JOptionPane.ERROR_MESSAGE);
				}
				try {
					value = todayURL.getText();
					new URL(value);
					Settings.getInstance().setToday(todayLabel.getText() + "::" + value);
				} catch (MalformedURLException e) {
					JOptionPane.showMessageDialog(frame, value + " is not a valid url, please try again.", "Warning: Invalid URL", JOptionPane.ERROR_MESSAGE);
				}
				try {
					value = tomorrowURL.getText();
					new URL(value);
					Settings.getInstance().setTomorrow(tomorrowLabel.getText() + "::" + value);
				} catch (MalformedURLException e) {
					JOptionPane.showMessageDialog(frame, value + " is not a valid url, please try again.", "Warning: Invalid URL", JOptionPane.ERROR_MESSAGE);
				}
				updateMainSettingsPanel(true);
			}
		});
		GridBagConstraints gbc_btnSaveChanges = new GridBagConstraints();
		gbc_btnSaveChanges.weighty = 0.1;
		gbc_btnSaveChanges.anchor = GridBagConstraints.SOUTH;
		gbc_btnSaveChanges.gridx = 0;
		gbc_btnSaveChanges.gridy = 5;
		mainSettingsPanel.add(btnSaveChanges, gbc_btnSaveChanges);

		updateMainSettingsPanel(false);
	}

	private void createFeedSettingsPanel() {
		JPanel feedSettingsPanel = new JPanel();
		settingsPanel.add(feedSettingsPanel, settingsItems.get(1));
		GridBagLayout gbl_feedSettingsPanel = new GridBagLayout();
		gbl_feedSettingsPanel.columnWidths = new int[]{500};
		gbl_feedSettingsPanel.rowHeights = new int[]{257, 20};
		gbl_feedSettingsPanel.columnWeights = new double[]{1.0};
		gbl_feedSettingsPanel.rowWeights = new double[]{1.0, 0.0};
		feedSettingsPanel.setLayout(gbl_feedSettingsPanel);

		feedTableModel = new DefaultTableModel(
				new Object[][] {},
				new String[] {"Name", "URL", "Priority"});
		feedTable = new JTable();
		JScrollPane feedScrollPane = new JScrollPane();

		GridBagConstraints gbc_feedScrollPane = new GridBagConstraints();
		gbc_feedScrollPane.weighty = 0.1;
		gbc_feedScrollPane.fill = GridBagConstraints.BOTH;
		gbc_feedScrollPane.insets = new Insets(0, 0, 5, 0);
		gbc_feedScrollPane.gridx = 0;
		gbc_feedScrollPane.gridy = 0;
		feedSettingsPanel.add(feedScrollPane, gbc_feedScrollPane);

		feedScrollPane.setViewportView(feedTable);
		feedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		feedTable.setModel(feedTableModel);
		feedTableModel.addTableModelListener(new TableModelListener() {
			@Override
			public void tableChanged(TableModelEvent e) {
				int row = e.getFirstRow();
				int col = e.getColumn();

				switch (e.getType()) {
				case TableModelEvent.INSERT:
					//Unused
					break;
				case TableModelEvent.UPDATE:
					ArrayList<Feed> feeds = new ArrayList<Feed>(); 
					feeds.addAll(Settings.getInstance().getFeeds());
					Feed feed = feeds.get(row);
					String value = (String) feedTableModel.getValueAt(row, col);
					if(col==0 && !value.isEmpty()) {
						feed.setLabel(value);
					}
					else if(col==1 && !value.isEmpty()) {
						try {
							new URL(value);
							feed.setLink(value);
						}
						catch (MalformedURLException exception) {
							JOptionPane.showMessageDialog(frame, value + " is not a valid url, please try again.", "Warning: Invalid url", JOptionPane.ERROR_MESSAGE);
						}
					}
					else if(col==2) {
						try {
							feed.setPriority(Integer.parseInt(value));
						}
						catch (NumberFormatException exception) {
							JOptionPane.showMessageDialog(frame, value + " is not an integer, please try again.", "Warning: Not an integer", JOptionPane.ERROR_MESSAGE);
						}
					}
					updateFeedTable(true);
					break;
				case TableModelEvent.DELETE:
					//Unused
					break;
				}
			}
		});

		feedTable.getColumnModel().getColumn(1).setPreferredWidth(300);

		JPanel feedSettingsButtonPanel = new JPanel();
		GridBagConstraints gbc_feedSettingsButtonPanel = new GridBagConstraints();
		gbc_feedSettingsButtonPanel.weightx = 0.1;
		gbc_feedSettingsButtonPanel.fill = GridBagConstraints.BOTH;
		gbc_feedSettingsButtonPanel.gridx = 0;
		gbc_feedSettingsButtonPanel.gridy = 1;
		feedSettingsPanel.add(feedSettingsButtonPanel, gbc_feedSettingsButtonPanel);

		JButton btnAddFeed = new JButton("Add Feed");
		btnAddFeed.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				String inputLabel = JOptionPane.showInputDialog(frame, "Enter the feed name: ");
				String inputURL = JOptionPane.showInputDialog(frame, "Enter the feed URL: ");
				String inputPriority = JOptionPane.showInputDialog(frame, "Enter the feed priority: ");
				try {
					new URL(inputURL);
					int priority = Integer.parseInt(inputPriority);
					Feed feed = new Feed(inputLabel, inputURL, priority);
					Settings.getInstance().addFeed(feed);
					updateFeedTable(true);
				} catch (MalformedURLException ex) {
					JOptionPane.showMessageDialog(frame, inputURL + " is not a valid url, please try again.", "Warning: Invalid url", JOptionPane.ERROR_MESSAGE);
				} catch (NumberFormatException ex) {
					JOptionPane.showMessageDialog(frame, inputPriority + " is not a number, please try again.", "Warning: Not a number ", JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		feedSettingsButtonPanel.add(btnAddFeed);

		JButton btnDeleteFeed = new JButton("Delete Feed");
		btnDeleteFeed.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = feedTable.getSelectedRow();
				if(row==-1) {
					JOptionPane.showMessageDialog(frame, "Please select a feed in the above table first.", "Error", JOptionPane.ERROR_MESSAGE);
				}
				else {
					Settings.getInstance().removeFeed(row);
					updateFeedTable(true);
				}
			}
		});
		feedSettingsButtonPanel.add(btnDeleteFeed);

		updateFeedTable(false);
	}

	private void createsearchettingsPanel() {
		JPanel searchettingsPanel = new JPanel();
		settingsPanel.add(searchettingsPanel, settingsItems.get(2));
		GridBagLayout gbl_searchettingsPanel = new GridBagLayout();
		gbl_searchettingsPanel.columnWidths = new int[]{500};
		gbl_searchettingsPanel.rowHeights = new int[]{257, 20};
		gbl_searchettingsPanel.columnWeights = new double[]{1.0};
		gbl_searchettingsPanel.rowWeights = new double[]{1.0, 0.0};
		searchettingsPanel.setLayout(gbl_searchettingsPanel);

		searchTableModel = new DefaultTableModel(
				new Object[][] {},
				new String[] {"Label", "URL"});
		searchTable = new JTable();
		JScrollPane searchcrollPane = new JScrollPane();

		GridBagConstraints gbc_searchcrollPane = new GridBagConstraints();
		gbc_searchcrollPane.weighty = 0.1;
		gbc_searchcrollPane.fill = GridBagConstraints.BOTH;
		gbc_searchcrollPane.insets = new Insets(0, 0, 5, 0);
		gbc_searchcrollPane.gridx = 0;
		gbc_searchcrollPane.gridy = 0;
		searchettingsPanel.add(searchcrollPane, gbc_searchcrollPane);

		searchcrollPane.setViewportView(searchTable);
		searchTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		searchTable.setModel(searchTableModel);
		searchTableModel.addTableModelListener(new TableModelListener() {
			@Override
			public void tableChanged(TableModelEvent e) {
				int row = e.getFirstRow();
				int col = e.getColumn();

				switch (e.getType()) {
				case TableModelEvent.INSERT:
					//Unused
					break;
				case TableModelEvent.UPDATE:
					ArrayList<Search> searches = new ArrayList<Search>();
					searches.addAll(Settings.getInstance().getSearches());
					Search search = searches.get(row);
					String label = search.getLabel();
					String url = search.getLink();
					String value = (String) searchTableModel.getValueAt(row, col);
					if(col==0 && !value.isEmpty()) {
						label = value;
					}
					if(col==1) {
						try {
							new URL(value);
							if(value.contains("#showtitle#")) {
								url = value;
							}
							else {
								JOptionPane.showMessageDialog(frame, value + " must contain the search parameter #showtitle#, please try again.", "Warning: Invalid url", JOptionPane.ERROR_MESSAGE);		
							}
						}
						catch (MalformedURLException exception) {
							//searchTableModel.setValueAt(""+url,row, col);
							JOptionPane.showMessageDialog(frame, value + " is not a valid url, please try again.", "Warning: Invalid url", JOptionPane.ERROR_MESSAGE);
						}

					}
					search.setLabel(label);
					search.setLink(url);
					updatesearchTable(true);
					break;
				case TableModelEvent.DELETE:
					//Unused
					break;
				}
			}
		});

		searchTable.getColumnModel().getColumn(1).setPreferredWidth(400);

		JPanel searchettingsButtonPanel = new JPanel();
		GridBagConstraints gbc_searchettingsButtonPanel = new GridBagConstraints();
		gbc_searchettingsButtonPanel.weightx = 0.1;
		gbc_searchettingsButtonPanel.fill = GridBagConstraints.BOTH;
		gbc_searchettingsButtonPanel.gridx = 0;
		gbc_searchettingsButtonPanel.gridy = 1;
		searchettingsPanel.add(searchettingsButtonPanel, gbc_searchettingsButtonPanel);

		JButton btnaddsearch = new JButton("Add Search");
		btnaddsearch.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				String inputLabel = JOptionPane.showInputDialog(frame, "Enter the search label: ");
				String inputURL = JOptionPane.showInputDialog(frame, "Enter the search URL (use #showtitle# in place of the search string): ");
				try {
					new URL(inputURL);
					if(inputURL.contains("#showtitle#")) {
						Settings.getInstance().addSearch(inputLabel, inputURL);
					}
					else {
						JOptionPane.showMessageDialog(frame, inputURL + " must contain the search parameter #showtitle#, please try again.", "Warning: Invalid url", JOptionPane.ERROR_MESSAGE);
					}
					updatesearchTable(true);
				} catch (MalformedURLException ex) {
					JOptionPane.showMessageDialog(frame, inputURL + " is not a valid url, please try again.", "Warning: Invalid url", JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		searchettingsButtonPanel.add(btnaddsearch);

		JButton btnDeletesearch = new JButton("Delete Search");
		btnDeletesearch.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int row = searchTable.getSelectedRow();
				if(row==-1) {
					JOptionPane.showMessageDialog(frame, "Please select a search url in the above table first.", "Error", JOptionPane.ERROR_MESSAGE);
				}
				else {
					Settings.getInstance().removeSearch(row);
					updatesearchTable(true);
				}
			}
		});
		searchettingsButtonPanel.add(btnDeletesearch);

		updatesearchTable(false);
	}

	void updateShowTable(boolean doUpdates) {
		if(doUpdates) ShowLibrary.getInstance().doUpdates();
		showTableModel.setRowCount(0);
		for (Show show : ShowLibrary.getInstance().shows){
			showTableModel.addRow(new Object[]{show.getTitle(), show.getCurSeason(), show.getLastEpisode()});
		}
	}

	private void updateFeedTable(boolean doUpdates) {
		if(doUpdates) ShowLibrary.getInstance().doUpdates();
		feedTableModel.setRowCount(0);
		for(Feed feed : Settings.getInstance().getFeeds()) {
			feedTableModel.addRow(new Object[]{feed.getLabel(), feed.getLink(), feed.getPriority()});
		}
	}

	private void updatesearchTable(boolean doUpdates) {
		if(doUpdates) ShowLibrary.getInstance().doUpdates();
		searchTableModel.setRowCount(0);
		for(Search search : Settings.getInstance().getSearches()) {
			String label = search.getLabel();
			String url = search.getLink();
			searchTableModel.addRow(new Object[]{label, url});
		}
	}

	private void updateMainSettingsPanel(boolean doUpdates) {
		if(doUpdates) ShowLibrary.getInstance().doUpdates();
		chckbxFindNewShows.setSelected(Settings.getInstance().isFindNewShows());
		chckbxTrackMiniseries.setSelected(Settings.getInstance().isFindMiniSeries());
		todayLabel.setText(Settings.getInstance().getToday().getLabel());
		todayURL.setText(Settings.getInstance().getToday().getLink().toString());
		tomorrowLabel.setText(Settings.getInstance().getTomorrow().getLabel());
		tomorrowURL.setText(Settings.getInstance().getTomorrow().getLink().toString());
		delayTextField.setText("" + Settings.getInstance().getDelay());
	}
}
